package com.icarsaas.saas.common.page;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.icarsaas.saas.common.utils.CookieUtils;

import cn.hutool.json.JSONUtil;

/**
 * 封装table查询数据
 *
 * @author Yujie Yang
 * @date 2018/7/17 18:42
 * @return
 */
public class SoulPage<T> {

    /**
     * layui表格必须参数⬇⬇⬇⬇⬇⬇
     */
    private Integer code = 0;
    private String msg = "";
    /**
     * 总记录
     */
    private long count;
    /**
     * 显示的记录
     */
    private List<T> data;

    /**
     * 请求条件
     */
    @JsonIgnore
    private T obj;
    /**
     * 查询条件
     */
    @JsonIgnore
    private Map<String, Object> condition = new HashMap<>();
    
    /**
     * 请求参数⬇⬇⬇⬇⬇⬇
     */

    /**
     * 当前页 从1开始
     */
    @JsonIgnore
    private Integer page=1;
    /**
     * 页大小
     */
    @JsonIgnore
    private Integer limit=100000000;

    /**
     * 查询列数据
     */
    @JsonIgnore
    private String columns;

    /**
     * 表格列类型
     */
    @JsonIgnore
    private String tableFilterType;
    /**
     * 筛选信息
     */
    @JsonIgnore
    private String filterSos;

    /**
     * 排序信息
     */
    @JsonIgnore
    private String field;
    @JsonIgnore
    private String order = "asc";
    
    /**
	 * 分页是否有效
	 * 
	 * @return this.limit==-1
	 */
	public boolean isDisabled() {
		return this.page == -1;
	}

	/**
	 * 是否进行总数统计
	 * 
	 * @return this.count==-1
	 */
	public boolean isNotCount() {
		return this.count == -1;
	}
    
    public SoulPage () {

    }
    
    /**
   	 * 构造方法
   	 * 
   	 * @param request 传递 repage 参数，来记住页码
   	 * @param response 用于设置 Cookie，记住页码
   	 */
   	public SoulPage(HttpServletRequest request, HttpServletResponse response) {
   		this(request, response, -2);
   	}

   	/**
   	 * 构造方法
   	 * @param request 传递 repage 参数，来记住页码
   	 * @param response 用于设置 Cookie，记住页码
   	 * @param limit 分页大小，如果传递 -1 则为不分页，返回所有数据
   	 */
   	public SoulPage(HttpServletRequest request, HttpServletResponse response, int pageSize) {
   		// 设置页码参数（传递repage参数，来记住页码）
   		String page = request.getParameter("page");
   		if (StringUtils.isNumeric(page)) {
   			CookieUtils.setCookie(response, "page", page);
   			this.setPage(Integer.parseInt(page));
   		}/* else if (request.getParameter("repage") != null) {
   			no = CookieUtils.getCookie(request, "pageNo");
   			if (StringUtils.isNumeric(no)) {
   				this.setPageNo(Integer.parseInt(no));
   			}
   		}*/
   		// 设置页面大小参数（传递repage参数，来记住页码大小）
   		String limit = request.getParameter("limit");
   		if (StringUtils.isNumeric(limit)) {
   			CookieUtils.setCookie(response, "limit", limit);
   			this.setLimit(Integer.parseInt(limit));
   		} /*else if (request.getParameter("repage") != null&&StringUtils.isNumeric(size)) {
   			this.setPageSize(Integer.parseInt(size));
   		}*/
   		if (pageSize != -2) {
   			this.page = pageSize;
   		}
   		// 设置排序参数
   		String orderBy = request.getParameter("orderBy");
   		if (StringUtils.isNotBlank(orderBy)) {
   			this.setOrder(orderBy);
   		}
   	}

   	/**
   	 * 构造方法
   	 * 
   	 * @param page 当前页码
   	 * @param limit 分页大小
   	 */
   	public SoulPage(int page, int limit) {
   		this(page, limit, 0);
   	}

   	/**
   	 * 构造方法
   	 * 
   	 * @param page 当前页码
   	 * @param limit 分页大小
   	 * @param count 数据条数
   	 */
   	public SoulPage(int page, int limit, long count) {
   		this(page, limit, count, new ArrayList<T>());
   	}

   	/**
   	 * 构造方法
   	 * 
   	 * @param page 当前页码
   	 * @param limit 分页大小
   	 * @param count 数据条数
   	 * @param list 本页数据对象列表
   	 */
   	public SoulPage(int page, int limit, long count, List<T> list) {
   		this.setCount(count);
   		this.setPage(page);
   		this.limit = limit;
   		this.setData(list);
   	}
       
    
    public SoulPage (Integer page, Integer limit) {
        this.page = page;
        this.limit = limit;
    }

    public List<FilterSoul> getFilterSos() {
//        return JSON.parseArray(filterSos, FilterSoul.class);
        return JSONUtil.toList(JSONUtil.parseArray(filterSos), FilterSoul.class);
    }

    public void setFilterSos(String filterSos) {
        this.filterSos = filterSos;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public long getCount() {
        return count;
    }

    public void setCount(long count) {
        this.count = count;
    }

    public List<T> getData() {
        return data;
    }

    @SuppressWarnings("unchecked")
	public Object setData(List<T> data) {
    	boolean flag = isColumn();
        if (flag) {
            Map<String, Map<String, String>> typeMap = getTypeMap();
            Map<String, Set<String>> columnMap = new HashMap<>();
            for (T datum : data) {
                for (String column : getColumns()) {
                    columnMap.computeIfAbsent(column, k -> new HashSet<>());
                    Object columnObject = null;
                    if (datum instanceof Map) {
                        columnObject = ((Map<String, ?>)datum).get(column);
                    } else {
                        try {
                            columnObject = ReflectHelper.getValueByFieldName(datum, column);
                        } catch (NoSuchFieldException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    if (columnObject != null) { //空值不展示
                        columnMap.get(column).add(getFormatValue(typeMap, column, columnObject));
                    }
                }
            }
            Map<String, List<String>> columnSortMap = new HashMap<>();
            Iterator<Map.Entry<String, Set<String>>> it = columnMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, Set<String>> entry = it.next();
                ArrayList<String> list = new ArrayList<>(entry.getValue());
                columnSortMap.put(entry.getKey(), list);
            }
            return columnSortMap;
        } else {
            this.data = data;
            return this;
        }
    }

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getLimit() {
        return limit;
    }

    public void setLimit(Integer limit) {
        this.limit = limit;
    }

    public int getOffset() {
        return (page - 1) * limit;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }

    public List<String> getColumns() {
//        return StringUtils.isNotBlank(columns)? JSON.parseArray(columns, String.class) : new ArrayList<>();
    	List<String> list = StringUtils.isNotBlank(columns) ? JSONUtil.toList(JSONUtil.parseArray(columns), String.class) : new ArrayList<>();
        return list;
    }

    public void setColumns(String columns) {
        this.columns = columns;
    }

    public String getTableFilterType() {
        return tableFilterType;
    }

    public void setTableFilterType(String tableFilterType) {
        this.tableFilterType = tableFilterType;
    }


    /**
     * 结构化 Filter type
     * @return
     */
    @JsonIgnore
    public Map<String, Map<String, String>> getTypeMap() {
        Map<String, Map<String, String>> typeMap = new HashMap<>();
        if (StringUtils.isNotEmpty(tableFilterType)) {
//            Map<String, String> filterType = JSON.parseObject(tableFilterType, Map.class);
            @SuppressWarnings("unchecked")
			Map<String, String> filterType = JSONUtil.toBean(tableFilterType, Map.class);
            filterType.forEach((k,v)->{
                Map<String, String> map = new HashMap<>();
                map.put("type", v.substring(0, v.indexOf("[")));
                map.put("value",v.substring(v.indexOf("[")+1, v.indexOf("]")) );
                typeMap.put(k, map);
            });
        }
        return typeMap;
    }

    /**
     * 根据类型转换最终的值
     * @param typeMap
     * @param column
     * @param columnObject
     * @return
     */
    public String getFormatValue (Map<String, Map<String, String>> typeMap, String column, Object columnObject) {
        String columnValue;
        if (typeMap.containsKey(column)) {
            if ("date".equalsIgnoreCase(typeMap.get(column).get("type")) && columnObject instanceof Date) {
                columnValue = dateFormat((Date) columnObject, typeMap.get(column).get("value"));
            } else {
                columnValue = (String) columnObject;
            }
        } else {
            if (columnObject instanceof Date) {
                columnValue = dateFormat((Date) columnObject, null);
            } else {
                columnValue = String.valueOf(columnObject) ;
            }
        }
        return columnValue;
    }

    /**
     * 是否是列查询
     * @return
     */
    public boolean isColumn () {
        return !getColumns().isEmpty();
    }

    public Map<String, Object> getCondition() {
        return condition;
    }

    public void setCondition(Map<String, Object> condition) {
        this.condition = condition;
    }

    private String dateFormat(Date date, String format) {
        if (StringUtils.isBlank(format)) {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        } else {
            return new SimpleDateFormat(format).format(date);
        }
    }
    

	/**
	 * 获取 Hibernate FirstResult
	 */
	public int getFirstResult() {
//		initialize();
		int firstResult = (getPage() - 1) * getLimit();
		if (firstResult >= getCount()) {
			firstResult = 0;
		}
		return firstResult;
	}

	/**
	 * 获取 Hibernate MaxResults
	 */
	public int getMaxResults() {
		int maxResults = getPage() * getLimit();
		return maxResults;
	}

    /**
     * 构造方法
     * @param params
     * @param soulPage
     * @return
     */
   	public SoulPage<T> setParams(Map<String, Object> params, SoulPage<T> soulPage) {
   		// 设置页码参数（传递repage参数，来记住页码）,同时去掉相关的参数
   		if (params != null) {
   			if (params.containsKey("page")) {
   				soulPage.setPage((Integer) params.get("page"));
   				params.remove("page");
   			}
   			// 设置页面大小参数（传递repage参数，来记住页码大小）
   			if (params.containsKey("limit")) {
   				soulPage.setLimit((Integer) params.get("limit"));
   				params.remove("limit");
   			}
   			// 设置排序参数
   			if (params.containsKey("order") && params.containsKey("field")) {
   				soulPage.setField((String) params.get("field"));
   				soulPage.setOrder((String) params.get("order"));
   				params.remove("field");
   				params.remove("order");
   			}
   			// 设置表头内查询
   			if (params.containsKey("filterSos")) {
   				String filterSos = (String) params.get("filterSos");
   				soulPage.setFilterSos(filterSos);
   				params.remove("filterSos");
   			}
   		}
   		return soulPage;
   	}
	
}